/*
@STI LICENSE
(C) 2006-2008 Universit�t Innsbruck.

This file is part of myOntology.

myOntologyis free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

myOntologyis distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with myOntology.  If not, see <http://www.gnu.org/licenses/>.

@STI LICENSE */
/**
 * 
 */
package org.myontology.controller;

import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

import org.apache.log4j.Logger;
import org.myontology.controller.selectors.TrueSelector;

/**
 * @author <a href="michael.hackl@sti2.at">Michael Hackl</a>
 * Project: Myontology - www.myontology.org
 * STI
 *
 */
public abstract class Selector {

	protected Logger logger = Logger.getLogger(getClass());
	
	private AbstractController controller;
	private Set<Selector> andSelectors = new CopyOnWriteArraySet<Selector>();
	private Set<Selector> otherwiseSelectors = new CopyOnWriteArraySet<Selector>();
	private Action action;
	private PageProvider pageProvider;
	
	public Selector and(Selector andSelector) {
		andSelectors.add(andSelector);
		andSelector.setController(controller);
		return andSelector;
	}
	
	public Selector otherwise(Selector otherwiseSelector) {
		otherwiseSelectors.add(otherwiseSelector);
		otherwiseSelector.setController(controller);
		return otherwiseSelector;
	}
	
	public Selector otherwise() {
		return otherwise(new TrueSelector());
	}
	
	public Selector onSelection(Action action,PageProvider provider) {
		this.action = action;
		pageProvider=provider;
		return this;
	}
	
	protected abstract boolean check(AttributeHolder attributes);
	
	public PageProvider select(AttributeHolder attributes) throws Exception{
		PageProvider nextProvider = null;
		if (check(attributes)) {
			logger.debug("selected: "+toString());
			if (action!=null) {
				controller.executeAction(action, attributes);
			}
			if (pageProvider!=null) {
				logger.debug("pageProvider: "+pageProvider.toString());
				return pageProvider;
			}
			nextProvider = searchNextSelectors(attributes, nextProvider,
					andSelectors);
		}
		else {
//			logger.debug("otherwise branch of: "+toString());
			nextProvider = searchNextSelectors(attributes, nextProvider,
					otherwiseSelectors);
		}
		return nextProvider;
	}

	private PageProvider searchNextSelectors(AttributeHolder attributes,
			PageProvider nextProvider, Set<Selector> selectors) throws Exception {
		for (Iterator<Selector> it = selectors.iterator();it.hasNext();) {
			Selector next = it.next();
//			if (next.check(attributes)) {
				nextProvider = next.select(attributes);
				if (nextProvider!=null)
					break;
//			}
		}
		return nextProvider;
	}

	public void setController(AbstractController controller) {
		this.controller=controller;
		
	}
	
}
